namespace SubhadraSolutions.Sharp.Logging.Adapters.Log4Net
{
    using log4net;
    using log4net.Config;
    using SubhadraSolutions.Sharp.Logging.Adapters.Log4Net.Context;
    using SubhadraSolutions.Sharp.Logging.Context;
    using SubhadraSolutions.Sharp.Logging.Contracts;
    using SubhadraSolutions.Sharp.Utils;
    using System.Collections.Concurrent;

    public sealed class LoggerFactory : AbstractInitializable
    {
        #region Fields

        private static readonly LoggerFactory _instance = new LoggerFactory();

        private readonly ConcurrentDictionary<ILogger, ILog> _loggers =
            new ConcurrentDictionary<ILogger, ILog>();

        #endregion Fields

        #region Constructors

        private LoggerFactory()
        {
            UseLog4Net = false;
        }

        #endregion Constructors

        #region Properties

        public static LoggerFactory Instance
        {
            get { return _instance; }
        }

        public ILog DefaultLogger
        {
            get { return GetLogger(string.Empty); }
        }

        public bool UseLog4Net
        {
            get;
            private set;
        }

        #endregion Properties

        #region Methods

        public ILog GetLogger(string loggerName)
        {
            Initialize();
            if (UseLog4Net)
            {
                return LogManager.GetLogger(loggerName);
            }
            ILogger logger = LoggerLogPublisherFactory.Instance.GetLogger(loggerName);
            return logger == null
                ? null
                : _loggers.GetOrAdd(logger, key => (new LoggerAsLogAdapter(logger)));
        }

        protected override void InitializeProtected()
        {
            if (UseLog4Net)
            {
                XmlConfigurator.Configure();
            }
            else
            {
                LoggingContext.Instance.Strategy = new Log4NetGlobalContextStrategy();
            }
        }

        #endregion Methods
    }
}